/**
 * The MOSES project, model based software engineering of networked embedded systems.
 * 
 * Copyright (C) 2010-2013, University of Applied Sciences Wildau,
 * Telematics Research Group, http://www.tm.th-wildau.de/research-group
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses>.
 * 
 * Contributors:
 *     University of Applied Sciences Wildau - initial API and implementation
 * 
 * If you are interested in a commercial license please contact us via
 * e-mail: ralf.vandenhouten@th-wildau.de.
 */
package de.thwildau.tm.moses.asn1.generator;

import com.google.common.base.Objects;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
import de.thwildau.tm.moses.asn1.asn1.AlternativeTypeList;
import de.thwildau.tm.moses.asn1.asn1.AnyDefinedNamedType;
import de.thwildau.tm.moses.asn1.asn1.BitStringType;
import de.thwildau.tm.moses.asn1.asn1.ChoiceType;
import de.thwildau.tm.moses.asn1.asn1.ClassNumber;
import de.thwildau.tm.moses.asn1.asn1.ComponentOfType;
import de.thwildau.tm.moses.asn1.asn1.ComponentType;
import de.thwildau.tm.moses.asn1.asn1.ComponentTypeList;
import de.thwildau.tm.moses.asn1.asn1.DefinedType;
import de.thwildau.tm.moses.asn1.asn1.ElementSetSpec;
import de.thwildau.tm.moses.asn1.asn1.EnumeratedType;
import de.thwildau.tm.moses.asn1.asn1.EnumerationItem;
import de.thwildau.tm.moses.asn1.asn1.IA5String;
import de.thwildau.tm.moses.asn1.asn1.IntegerType;
import de.thwildau.tm.moses.asn1.asn1.NamedBit;
import de.thwildau.tm.moses.asn1.asn1.NamedComponentType;
import de.thwildau.tm.moses.asn1.asn1.NamedNumber;
import de.thwildau.tm.moses.asn1.asn1.NamedType;
import de.thwildau.tm.moses.asn1.asn1.OctetStringType;
import de.thwildau.tm.moses.asn1.asn1.SequenceOfType;
import de.thwildau.tm.moses.asn1.asn1.SequenceType;
import de.thwildau.tm.moses.asn1.asn1.Tag;
import de.thwildau.tm.moses.asn1.asn1.TaggedType;
import de.thwildau.tm.moses.asn1.asn1.Type;
import de.thwildau.tm.moses.asn1.asn1.TypeAssignment;
import de.thwildau.tm.moses.asn1.generator.GeneratorExtensions;
import de.thwildau.tm.moses.asn1.generator.JavaTemplates;
import de.thwildau.tm.moses.asn1.util.Asn1ElementFinder;
import de.thwildau.tm.moses.asn1.util.EObjectResourceDescription;
import de.thwildau.tm.moses.asn1.util.NamesConverter;
import de.thwildau.tm.moses.asn1.util.generator.GenConstraint;
import de.thwildau.tm.moses.asn1.util.generator.GenSizeConstraint;
import de.thwildau.tm.moses.asn1.util.generator.GenValueRangeConstraint;
import java.util.Arrays;
import java.util.List;
import org.eclipse.emf.codegen.util.ImportManager;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtend2.lib.StringConcatenation;
import org.eclipse.xtext.generator.IFileSystemAccess;
import org.eclipse.xtext.generator.IGenerator;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.xbase.lib.Extension;
import org.eclipse.xtext.xbase.lib.InputOutput;
import org.eclipse.xtext.xbase.lib.IntegerRange;
import org.eclipse.xtext.xbase.lib.IteratorExtensions;
import org.eclipse.xtext.xbase.lib.StringExtensions;

@SuppressWarnings("all")
public class Asn1Generator implements IGenerator {
  @Inject
  @Extension
  private NamesConverter namesConverter;
  
  @Inject
  @Extension
  private Asn1ElementFinder finder;
  
  private IFileSystemAccess fsa;
  
  public void doGenerate(final Resource resource, final IFileSystemAccess fsa) {
    this.fsa = fsa;
    TreeIterator<EObject> _allContents = resource.getAllContents();
    Iterable<EObject> _iterable = IteratorExtensions.<EObject>toIterable(_allContents);
    Iterable<TypeAssignment> _filter = Iterables.<TypeAssignment>filter(_iterable, TypeAssignment.class);
    for (final TypeAssignment e : _filter) {
      {
        Type _type = e.getType();
        String _name = e.getName();
        EObjectResourceDescription<Type> desc = this.namesConverter.<Type>getResourceDescription(_type, _name);
        String _filePath = desc.getFilePath();
        CharSequence _generateFile = this.generateFile(desc);
        fsa.generateFile(_filePath, _generateFile);
      }
    }
  }
  
  public CharSequence generateFile(final EObjectResourceDescription<? extends Type> desc) {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _generateFileComment = JavaTemplates.generateFileComment();
    _builder.append(_generateFileComment, "");
    _builder.newLineIfNotEmpty();
    CharSequence _generatePackage = JavaTemplates.generatePackage(desc);
    _builder.append(_generatePackage, "");
    _builder.newLineIfNotEmpty();
    QualifiedName _packageName = desc.getPackageName();
    String _string = _packageName.toString();
    String _className = desc.getClassName();
    ImportManager _importManager = new ImportManager(_string, _className);
    ImportManager importManager = _importManager;
    _builder.newLineIfNotEmpty();
    Type _object = desc.getObject();
    CharSequence classBody = this.toClass(desc, importManager, _object);
    _builder.append("\t\t");
    _builder.newLineIfNotEmpty();
    String _computeSortedImports = importManager.computeSortedImports();
    _builder.append(_computeSortedImports, "");
    _builder.newLineIfNotEmpty();
    _builder.newLine();
    CharSequence _generateClassComment = JavaTemplates.generateClassComment(desc);
    _builder.append(_generateClassComment, "");
    _builder.newLineIfNotEmpty();
    CharSequence _println = InputOutput.<CharSequence>println(classBody);
    _builder.append(_println, "");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  protected CharSequence _toClass(final EObjectResourceDescription<SequenceType> desc, final ImportManager im, final SequenceType type) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("public class ");
    String _className = desc.getClassName();
    _builder.append(_className, "");
    _builder.append(" {");
    _builder.newLineIfNotEmpty();
    {
      ComponentTypeList _componentTypeList = type.getComponentTypeList();
      EList<ComponentType> _componentTypes = _componentTypeList.getComponentTypes();
      for(final ComponentType ct : _componentTypes) {
        _builder.append("\t");
        CharSequence _field = this.toField(ct, im);
        _builder.append(_field, "	");
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _toClass(final EObjectResourceDescription<ChoiceType> desc, final ImportManager im, final ChoiceType type) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("public class ");
    String _className = desc.getClassName();
    _builder.append(_className, "");
    _builder.append(" {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("public enum Identifier {");
    _builder.newLine();
    _builder.append("\t\t");
    AlternativeTypeList _alternativeTypeList = type.getAlternativeTypeList();
    EList<NamedType> namedTypeList = _alternativeTypeList.getNamedTypes();
    _builder.newLineIfNotEmpty();
    {
      int _size = namedTypeList.size();
      int _minus = (_size - 1);
      IntegerRange _upTo = new IntegerRange(0, _minus);
      for(final Integer i : _upTo) {
        _builder.append("\t\t");
        int _size_1 = namedTypeList.size();
        int _minus_1 = (_size_1 - 1);
        boolean isLast = ((i).intValue() == _minus_1);
        _builder.newLineIfNotEmpty();
        _builder.append("\t\t");
        NamedType namedType = namedTypeList.get((i).intValue());
        _builder.newLineIfNotEmpty();
        _builder.append("\t\t");
        Type _type = namedType.getType();
        String _name = namedType.getName();
        CharSequence _enumFieldOfChoiceType = this.toEnumFieldOfChoiceType(_type, _name, im);
        _builder.append(_enumFieldOfChoiceType, "		");
        CharSequence _enumFieldDelimiter = GeneratorExtensions.enumFieldDelimiter(isLast);
        _builder.append(_enumFieldDelimiter, "		");
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("\t\t");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("private int id;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("private ");
    String _import = GeneratorExtensions.getImport(im, "java.lang.Class");
    _builder.append(_import, "		");
    _builder.append("<?> clazz;");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("private Identifier(int id, ");
    String _import_1 = GeneratorExtensions.getImport(im, "java.lang.Class");
    _builder.append(_import_1, "		");
    _builder.append("<?> clazz) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t\t");
    _builder.append("this.id = id;");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("this.clazz = clazz;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.newLine();
    _builder.append("\t\t");
    CharSequence _getterMethod = GeneratorExtensions.toGetterMethod("int", "id");
    _builder.append(_getterMethod, "		");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    String _import_2 = GeneratorExtensions.getImport(im, "java.lang.Class");
    String _plus = (_import_2 + "<?>");
    CharSequence _getterMethod_1 = GeneratorExtensions.toGetterMethod(_plus, "clazz");
    _builder.append(_getterMethod_1, "		");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private int choiceId = 0;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private Object element = null;");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public ");
    String _className_1 = desc.getClassName();
    _builder.append(_className_1, "	");
    _builder.append("() {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public ");
    String _className_2 = desc.getClassName();
    _builder.append(_className_2, "	");
    _builder.append("(int choiceId, ");
    String _import_3 = GeneratorExtensions.getImport(im, "java.lang.Object");
    _builder.append(_import_3, "	");
    _builder.append(" element) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append("this.choiceId = choiceId;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.element = element;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    CharSequence _setterGetterMethod = GeneratorExtensions.toSetterGetterMethod("int", "choiceId");
    _builder.append(_setterGetterMethod, "	");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    String _import_4 = GeneratorExtensions.getImport(im, "java.lang.Object");
    CharSequence _setterGetterMethod_1 = GeneratorExtensions.toSetterGetterMethod(_import_4, "element");
    _builder.append(_setterGetterMethod_1, "	");
    _builder.newLineIfNotEmpty();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _toClass(final EObjectResourceDescription<EnumeratedType> desc, final ImportManager im, final EnumeratedType type) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("public enum ");
    String _className = desc.getClassName();
    _builder.append(_className, "");
    _builder.append(" {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    EnumeratedType _object = desc.getObject();
    EList<EnumerationItem> enumerationItems = _object.getEnums();
    _builder.newLineIfNotEmpty();
    {
      int _size = enumerationItems.size();
      int _minus = (_size - 1);
      IntegerRange _upTo = new IntegerRange(0, _minus);
      for(final Integer i : _upTo) {
        _builder.append("\t");
        int _size_1 = enumerationItems.size();
        int _minus_1 = (_size_1 - 1);
        boolean isLast = ((i).intValue() == _minus_1);
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        EnumerationItem item = enumerationItems.get((i).intValue());
        _builder.newLineIfNotEmpty();
        {
          String _name = item.getName();
          boolean _notEquals = (!Objects.equal(_name, null));
          if (_notEquals) {
            _builder.append("\t");
            String _name_1 = item.getName();
            String _upperCase = _name_1.toUpperCase();
            _builder.append(_upperCase, "	");
            CharSequence _enumFieldDelimiter = GeneratorExtensions.enumFieldDelimiter(isLast);
            _builder.append(_enumFieldDelimiter, "	");
            _builder.newLineIfNotEmpty();
          } else {
            NamedNumber _number = item.getNumber();
            boolean _notEquals_1 = (!Objects.equal(_number, null));
            if (_notEquals_1) {
              _builder.append("\t");
              NamedNumber _number_1 = item.getNumber();
              String _name_2 = _number_1.getName();
              String _upperCase_1 = _name_2.toUpperCase();
              _builder.append(_upperCase_1, "	");
              _builder.append("(");
              NamedNumber _number_2 = item.getNumber();
              long _number_3 = _number_2.getNumber();
              _builder.append(_number_3, "	");
              _builder.append(")");
              CharSequence _enumFieldDelimiter_1 = GeneratorExtensions.enumFieldDelimiter(isLast);
              _builder.append(_enumFieldDelimiter_1, "	");
              _builder.newLineIfNotEmpty();
            }
          }
        }
      }
    }
    _builder.append("\t\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private int id;");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private ");
    String _className_1 = desc.getClassName();
    _builder.append(_className_1, "	");
    _builder.append("(int id) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append("this.id = id;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private ");
    String _className_2 = desc.getClassName();
    _builder.append(_className_2, "	");
    _builder.append("() {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append("this.id = -1;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.newLine();
    _builder.append("\t");
    CharSequence _getterMethod = GeneratorExtensions.toGetterMethod("int", "id");
    _builder.append(_getterMethod, "	");
    _builder.newLineIfNotEmpty();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _toClass(final EObjectResourceDescription<SequenceOfType> desc, final ImportManager im, final SequenceOfType type) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("public class ");
    String _className = desc.getClassName();
    _builder.append(_className, "");
    _builder.append(" {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    Type _type = type.getType();
    String sequenceOfReference = this.getReference(_type, im);
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    String _className_1 = desc.getClassName();
    String fieldName = this.namesConverter.toFieldName(_className_1);
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    String _import = GeneratorExtensions.getImport(im, "java.util.List");
    String _plus = (_import + "<");
    String _plus_1 = (_plus + sequenceOfReference);
    String fieldType = (_plus_1 + ">");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private ");
    _builder.append(fieldType, "	");
    _builder.append(" ");
    _builder.append(fieldName, "	");
    _builder.append(" = new ");
    String _import_1 = GeneratorExtensions.getImport(im, "java.util.ArrayList");
    _builder.append(_import_1, "	");
    _builder.append("<");
    _builder.append(sequenceOfReference, "	");
    _builder.append(">();");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public ");
    String _className_2 = desc.getClassName();
    _builder.append(_className_2, "	");
    _builder.append("() {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public ");
    String _className_3 = desc.getClassName();
    _builder.append(_className_3, "	");
    _builder.append("(");
    _builder.append(fieldType, "	");
    _builder.append(" initList) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append(fieldName, "		");
    _builder.append(".addAll(initList);");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    CharSequence _setterGetterMethod = GeneratorExtensions.toSetterGetterMethod(fieldType, fieldName);
    _builder.append(_setterGetterMethod, "	");
    _builder.newLineIfNotEmpty();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _toClass(final EObjectResourceDescription<BitStringType> desc, final ImportManager im, final BitStringType type) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("public class ");
    String _className = desc.getClassName();
    _builder.append(_className, "");
    _builder.append(" {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    String _className_1 = desc.getClassName();
    String fieldName = this.namesConverter.toFieldName(_className_1);
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    String fieldType = GeneratorExtensions.getImport(im, "java.util.BitSet");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    EList<NamedBit> _namedBits = type.getNamedBits();
    CharSequence _enum = this.toEnum(_namedBits);
    _builder.append(_enum, "	");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private ");
    _builder.append(fieldType, "	");
    _builder.append(" ");
    _builder.append(fieldName, "	");
    _builder.append(" = new ");
    _builder.append(fieldType, "	");
    _builder.append("();");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public ");
    String _className_2 = desc.getClassName();
    _builder.append(_className_2, "	");
    _builder.append("() {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public ");
    String _className_3 = desc.getClassName();
    _builder.append(_className_3, "	");
    _builder.append("(");
    _builder.append(fieldType, "	");
    _builder.append(" ");
    _builder.append(fieldName, "	");
    _builder.append(") {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append("this.");
    _builder.append(fieldName, "		");
    _builder.append(" = ");
    _builder.append(fieldName, "		");
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public ");
    String _className_4 = desc.getClassName();
    _builder.append(_className_4, "	");
    _builder.append("(");
    String _import = GeneratorExtensions.getImport(im, "java.lang.String");
    _builder.append(_import, "	");
    _builder.append(" string) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    CharSequence _setterGetterMethod = GeneratorExtensions.toSetterGetterMethod(fieldType, fieldName);
    _builder.append(_setterGetterMethod, "	");
    _builder.newLineIfNotEmpty();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _toClass(final EObjectResourceDescription<OctetStringType> desc, final ImportManager im, final OctetStringType type) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("public class ");
    String _className = desc.getClassName();
    _builder.append(_className, "");
    _builder.append(" {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    String _className_1 = desc.getClassName();
    String fieldName = this.namesConverter.toFieldName(_className_1);
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    String fieldType = this.getReference(type, im);
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    List<ElementSetSpec> _constrainst = this.finder.getConstrainst(type);
    GenConstraint<Long> constraint = this.finder.getConstraint(_constrainst);
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    CharSequence _constraintAnnotation = this.toConstraintAnnotation(constraint, im);
    _builder.append(_constraintAnnotation, "	");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("private ");
    _builder.append(fieldType, "	");
    _builder.append(" ");
    _builder.append(fieldName, "	");
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public ");
    String _className_2 = desc.getClassName();
    _builder.append(_className_2, "	");
    _builder.append("() {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append("this.");
    _builder.append(fieldName, "		");
    _builder.append(" = new ");
    _builder.append(fieldType, "		");
    _builder.append("(");
    String _constructorParam = this.getConstructorParam(constraint, false);
    _builder.append(_constructorParam, "		");
    _builder.append(");");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public ");
    String _className_3 = desc.getClassName();
    _builder.append(_className_3, "	");
    _builder.append("(");
    String _import = GeneratorExtensions.getImport(im, "java.lang.String");
    _builder.append(_import, "	");
    _builder.append(" string) throws ");
    String _import_1 = GeneratorExtensions.getImport(im, "java.io.IOException");
    _builder.append(_import_1, "	");
    _builder.append(" {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append("this.");
    _builder.append(fieldName, "		");
    _builder.append(" = new ");
    _builder.append(fieldType, "		");
    _builder.append("(");
    String _constructorParam_1 = this.getConstructorParam(constraint, true);
    _builder.append(_constructorParam_1, "		");
    _builder.append("string);");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    String _plus = ("" + fieldType);
    CharSequence _getterMethod = GeneratorExtensions.toGetterMethod(_plus, fieldName);
    _builder.append(_getterMethod, "	");
    _builder.newLineIfNotEmpty();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _toClass(final EObjectResourceDescription<IntegerType> desc, final ImportManager im, final IntegerType type) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("public class ");
    String _className = desc.getClassName();
    _builder.append(_className, "");
    _builder.append(" {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    String _className_1 = desc.getClassName();
    String _fieldName = this.namesConverter.toFieldName(_className_1);
    CharSequence _field = this.toField(type, im, _fieldName);
    _builder.append(_field, "	");
    _builder.newLineIfNotEmpty();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _toClass(final EObjectResourceDescription<DefinedType> desc, final ImportManager im, final DefinedType type) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("public class ");
    String _className = desc.getClassName();
    _builder.append(_className, "");
    _builder.append(" {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    String _className_1 = desc.getClassName();
    String _fieldName = this.namesConverter.toFieldName(_className_1);
    CharSequence _field = this.toField(type, im, _fieldName);
    _builder.append(_field, "	");
    _builder.newLineIfNotEmpty();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _toClass(final EObjectResourceDescription<? extends Object> desc, final ImportManager im, final Type type) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("public class ");
    String _className = desc.getClassName();
    _builder.append(_className, "");
    _builder.append(" {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("// TODO implement me for ");
    EClass _eClass = type.eClass();
    String _name = _eClass.getName();
    _builder.append(_name, "	");
    _builder.newLineIfNotEmpty();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  public CharSequence toEnum(final EList<NamedBit> namedBits) {
    StringConcatenation _builder = new StringConcatenation();
    {
      int _size = namedBits.size();
      boolean _greaterThan = (_size > 0);
      if (_greaterThan) {
        _builder.append("public enum Identifier {");
        _builder.newLine();
        _builder.append("\t");
        _builder.newLine();
        {
          int _size_1 = namedBits.size();
          int _minus = (_size_1 - 1);
          IntegerRange _upTo = new IntegerRange(0, _minus);
          for(final Integer i : _upTo) {
            _builder.append("\t");
            int _size_2 = namedBits.size();
            int _minus_1 = (_size_2 - 1);
            boolean isLast = ((i).intValue() == _minus_1);
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            NamedBit namedBit = namedBits.get((i).intValue());
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            String _identifier = namedBit.getIdentifier();
            String _enumField = this.namesConverter.toEnumField(_identifier);
            _builder.append(_enumField, "	");
            _builder.append("(");
            long _number = namedBit.getNumber();
            _builder.append(_number, "	");
            _builder.append(")");
            CharSequence _enumFieldDelimiter = GeneratorExtensions.enumFieldDelimiter(isLast);
            _builder.append(_enumFieldDelimiter, "	");
            _builder.newLineIfNotEmpty();
          }
        }
        _builder.append("\t");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("private int id;");
        _builder.newLine();
        _builder.append("\t");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("private Identifier(int id) {");
        _builder.newLine();
        _builder.append("\t\t");
        _builder.append("this.id = id;");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("}");
        _builder.newLine();
        _builder.append("\t");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("public int getId() {");
        _builder.newLine();
        _builder.append("\t\t");
        _builder.append("return id;\t");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("}");
        _builder.newLine();
        _builder.append("}");
        _builder.newLine();
      }
    }
    return _builder;
  }
  
  protected CharSequence _toField(final NamedComponentType type, final ImportManager im) {
    NamedType _namedType = type.getNamedType();
    Type _type = _namedType.getType();
    NamedType _namedType_1 = type.getNamedType();
    String _name = _namedType_1.getName();
    String _fieldName = this.namesConverter.toFieldName(_name);
    CharSequence _field = this.toField(_type, im, _fieldName);
    return _field;
  }
  
  protected CharSequence _toField(final ComponentOfType type, final ImportManager im) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("// TODO implement me");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _toField(final AnyDefinedNamedType type, final ImportManager im) {
    NamedType _definedType = type.getDefinedType();
    Type _type = _definedType.getType();
    String _name = type.getName();
    String _fieldName = this.namesConverter.toFieldName(_name);
    CharSequence _field = this.toField(_type, im, _fieldName);
    return _field;
  }
  
  protected CharSequence _toField(final DefinedType type, final ImportManager im, final String attributeName) {
    StringConcatenation _builder = new StringConcatenation();
    TypeAssignment _target = type.getTarget();
    EObjectResourceDescription<TypeAssignment> typeResource = this.namesConverter.<TypeAssignment>getResourceDescription(_target);
    _builder.newLineIfNotEmpty();
    _builder.newLine();
    _builder.append("private ");
    String _className = typeResource.getClassName();
    _builder.append(_className, "");
    _builder.append(" ");
    _builder.append(attributeName, "");
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    _builder.newLine();
    String _className_1 = typeResource.getClassName();
    CharSequence _setterGetterMethod = GeneratorExtensions.toSetterGetterMethod(_className_1, attributeName);
    _builder.append(_setterGetterMethod, "");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  protected CharSequence _toField(final ChoiceType type, final ImportManager im, final String attributeName) {
    StringConcatenation _builder = new StringConcatenation();
    EObjectResourceDescription<ChoiceType> desc = this.namesConverter.<ChoiceType>getResourceDescription(type, attributeName);
    _builder.newLineIfNotEmpty();
    String _filePath = desc.getFilePath();
    CharSequence _generateFile = this.generateFile(desc);
    this.fsa.generateFile(_filePath, _generateFile);
    _builder.newLineIfNotEmpty();
    _builder.newLine();
    _builder.append("private ");
    String _className = desc.getClassName();
    _builder.append(_className, "");
    _builder.append(" ");
    _builder.append(attributeName, "");
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    _builder.newLine();
    String _className_1 = desc.getClassName();
    CharSequence _setterGetterMethod = GeneratorExtensions.toSetterGetterMethod(_className_1, attributeName);
    _builder.append(_setterGetterMethod, "");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  protected CharSequence _toField(final IntegerType type, final ImportManager im, final String attributeName) {
    StringConcatenation _builder = new StringConcatenation();
    List<ElementSetSpec> _constrainst = this.finder.getConstrainst(type);
    GenConstraint<Long> constraint = this.finder.getConstraint(_constrainst);
    _builder.newLineIfNotEmpty();
    {
      EList<NamedNumber> _namedNumberList = type.getNamedNumberList();
      boolean _isEmpty = _namedNumberList.isEmpty();
      if (_isEmpty) {
        CharSequence _constraintAnnotation = this.toConstraintAnnotation(constraint, im);
        _builder.append(_constraintAnnotation, "");
        _builder.newLineIfNotEmpty();
        _builder.append("private ");
        String _import = GeneratorExtensions.getImport(im, "java.lang.Integer");
        _builder.append(_import, "");
        _builder.append(" ");
        _builder.append(attributeName, "");
        _builder.append(";");
        _builder.newLineIfNotEmpty();
        _builder.newLine();
        CharSequence _setterGetterMethod = GeneratorExtensions.toSetterGetterMethod("Integer", attributeName, constraint, im);
        _builder.append(_setterGetterMethod, "");
        _builder.newLineIfNotEmpty();
      } else {
        String _firstUpper = StringExtensions.toFirstUpper(attributeName);
        String enumName = (_firstUpper + "NamedNumber");
        _builder.newLineIfNotEmpty();
        _builder.newLine();
        _builder.append("public enum ");
        _builder.append(enumName, "");
        _builder.append(" implements ");
        String _import_1 = GeneratorExtensions.getImport(im, "de.thwildau.tm.moses.asn1.lang.NamedNumber");
        _builder.append(_import_1, "");
        _builder.append(" {");
        _builder.newLineIfNotEmpty();
        {
          EList<NamedNumber> _namedNumberList_1 = type.getNamedNumberList();
          int _size = _namedNumberList_1.size();
          int _minus = (_size - 1);
          IntegerRange _upTo = new IntegerRange(0, _minus);
          for(final Integer i : _upTo) {
            _builder.append("\t");
            EList<NamedNumber> _namedNumberList_2 = type.getNamedNumberList();
            NamedNumber namedNumber = _namedNumberList_2.get((i).intValue());
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            EList<NamedNumber> _namedNumberList_3 = type.getNamedNumberList();
            int _size_1 = _namedNumberList_3.size();
            int _minus_1 = (_size_1 - 1);
            boolean isLast = ((i).intValue() == _minus_1);
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            String _name = namedNumber.getName();
            String _enumField = this.namesConverter.toEnumField(_name);
            _builder.append(_enumField, "	");
            _builder.append("(");
            long _number = namedNumber.getNumber();
            _builder.append(_number, "	");
            _builder.append(")");
            CharSequence _enumFieldDelimiter = GeneratorExtensions.enumFieldDelimiter(isLast);
            _builder.append(_enumFieldDelimiter, "	");
            _builder.newLineIfNotEmpty();
          }
        }
        _builder.append("\t");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("private int number;");
        _builder.newLine();
        _builder.append("\t");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("private ");
        _builder.append(enumName, "	");
        _builder.append("(int number) {");
        _builder.newLineIfNotEmpty();
        _builder.append("\t\t");
        _builder.append("this.number = number;");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("}");
        _builder.newLine();
        _builder.append("\t");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("@");
        String _import_2 = GeneratorExtensions.getImport(im, "java.lang.Override");
        _builder.append(_import_2, "	");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        _builder.append("public int getNumber() {");
        _builder.newLine();
        _builder.append("\t\t");
        _builder.append("return number;\t");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("}");
        _builder.newLine();
        _builder.append("}");
        _builder.newLine();
        _builder.newLine();
        CharSequence _constraintAnnotation_1 = this.toConstraintAnnotation(constraint, im);
        _builder.append(_constraintAnnotation_1, "");
        _builder.newLineIfNotEmpty();
        _builder.append("private ");
        _builder.append(enumName, "");
        _builder.append(" ");
        _builder.append(attributeName, "");
        _builder.append(";");
        _builder.newLineIfNotEmpty();
        _builder.newLine();
        CharSequence _setterGetterMethod_1 = GeneratorExtensions.toSetterGetterMethod(enumName, attributeName, constraint, im);
        _builder.append(_setterGetterMethod_1, "");
        _builder.newLineIfNotEmpty();
      }
    }
    return _builder;
  }
  
  protected CharSequence _toField(final OctetStringType type, final ImportManager im, final String attributeName) {
    StringConcatenation _builder = new StringConcatenation();
    String typename = this.getReference(type, im);
    _builder.newLineIfNotEmpty();
    _builder.append("private ");
    _builder.append(typename, "");
    _builder.append(" ");
    _builder.append(attributeName, "");
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    _builder.newLine();
    String _string = typename.toString();
    CharSequence _setterGetterMethod = GeneratorExtensions.toSetterGetterMethod(_string, attributeName);
    _builder.append(_setterGetterMethod, "");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  protected CharSequence _toField(final IA5String type, final ImportManager im, final String attributeName) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("private ");
    String _import = GeneratorExtensions.getImport(im, "java.lang.String");
    _builder.append(_import, "");
    _builder.append(" ");
    _builder.append(attributeName, "");
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    _builder.newLine();
    String _import_1 = GeneratorExtensions.getImport(im, "java.lang.String");
    CharSequence _setterGetterMethod = GeneratorExtensions.toSetterGetterMethod(_import_1, attributeName);
    _builder.append(_setterGetterMethod, "");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  protected CharSequence _toField(final SequenceOfType type, final ImportManager im, final String attributeName) {
    StringConcatenation _builder = new StringConcatenation();
    String _import = GeneratorExtensions.getImport(im, "java.util.List");
    String _plus = (_import + "<");
    Type _type = type.getType();
    String _reference = this.getReference(_type, im);
    String _plus_1 = (_plus + _reference);
    String typename = (_plus_1 + ">");
    _builder.newLineIfNotEmpty();
    _builder.append("private ");
    _builder.append(typename, "");
    _builder.append(" ");
    _builder.append(attributeName, "");
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    _builder.newLine();
    String _string = typename.toString();
    CharSequence _setterGetterMethod = GeneratorExtensions.toSetterGetterMethod(_string, attributeName);
    _builder.append(_setterGetterMethod, "");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  protected CharSequence _toField(final Type type, final ImportManager im, final String attributeName) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("// TODO implement generateAttributeReference(");
    EClass _eClass = type.eClass();
    String _name = _eClass.getName();
    _builder.append(_name, "");
    _builder.append(" type, ");
    String _import = GeneratorExtensions.getImport(im, "java.lang.String");
    _builder.append(_import, "");
    _builder.append(" ");
    _builder.append(attributeName, "");
    _builder.append(")");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  protected CharSequence _toConstraintAnnotation(final GenSizeConstraint<Long> constraint, final ImportManager im) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("@");
    String _import = GeneratorExtensions.getImport(im, "de.thwildau.tm.moses.asn1.lang.SizeConstraint");
    _builder.append(_import, "");
    _builder.append("(max=");
    Long _max = constraint.getMax();
    _builder.append(_max, "");
    _builder.append("l)");
    return _builder;
  }
  
  protected CharSequence _toConstraintAnnotation(final GenValueRangeConstraint<Long> constraint, final ImportManager im) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("@");
    String _import = GeneratorExtensions.getImport(im, "de.thwildau.tm.moses.asn1.lang.ValueRangeConstraint");
    _builder.append(_import, "");
    _builder.append("(min=");
    Long _lower = constraint.getLower();
    _builder.append(_lower, "");
    _builder.append("l,max=");
    Long _upper = constraint.getUpper();
    _builder.append(_upper, "");
    _builder.append("l)");
    return _builder;
  }
  
  protected CharSequence _toConstraintAnnotation(final Void constraint, final ImportManager im) {
    StringConcatenation _builder = new StringConcatenation();
    return _builder;
  }
  
  protected CharSequence _toEnumFieldOfChoiceType(final Type type, final String enumFieldName, final ImportManager im) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("// TODO implement generateEnumFieldReference(Type type, ");
    String _import = GeneratorExtensions.getImport(im, "java.lang.String");
    _builder.append(_import, "");
    _builder.append(" enumFieldName)");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  protected CharSequence _toEnumFieldOfChoiceType(final TaggedType type, final String enumFieldName, final ImportManager im) {
    StringConcatenation _builder = new StringConcatenation();
    String _enumField = this.namesConverter.toEnumField(enumFieldName);
    _builder.append(_enumField, "");
    _builder.append("(");
    Tag _tag = type.getTag();
    ClassNumber _classNumber = _tag.getClassNumber();
    long _number = _classNumber.getNumber();
    _builder.append(_number, "");
    _builder.append(", ");
    Type _type = type.getType();
    String _reference = this.getReference(_type, im);
    _builder.append(_reference, "");
    _builder.append(".class)");
    return _builder;
  }
  
  protected String _getReference(final DefinedType type, final ImportManager im) {
    TypeAssignment _target = type.getTarget();
    EObjectResourceDescription<TypeAssignment> _resourceDescription = this.namesConverter.<TypeAssignment>getResourceDescription(_target);
    String _className = _resourceDescription.getClassName();
    return GeneratorExtensions.getImport(im, _className);
  }
  
  protected String _getReference(final OctetStringType type, final ImportManager im) {
    return GeneratorExtensions.getImport(im, "de.thwildau.tm.moses.asn1.lang.OctetString");
  }
  
  protected String _getReference(final Type type, final ImportManager im) {
    return "// TODO implement generateReference(Type type)";
  }
  
  private String getConstructorParam(final GenConstraint<Long> constraint, final boolean hasNextParam) {
    String _xblockexpression = null;
    {
      String _xifexpression = null;
      if (hasNextParam) {
        _xifexpression = ", ";
      } else {
        _xifexpression = "";
      }
      final String suffix = _xifexpression;
      String _switchResult = null;
      boolean _matched = false;
      if (!_matched) {
        if (constraint instanceof GenSizeConstraint) {
          final GenSizeConstraint<Long> _genSizeConstraint = (GenSizeConstraint<Long>)constraint;
          _matched=true;
          Long _max = _genSizeConstraint.getMax();
          return (_max + suffix);
        }
      }
      _xblockexpression = (_switchResult);
    }
    return _xblockexpression;
  }
  
  public CharSequence toClass(final EObjectResourceDescription<? extends Object> desc, final ImportManager im, final Type type) {
    if (desc != null
         && type instanceof BitStringType) {
      return _toClass(desc, im, (BitStringType)type);
    } else if (desc != null
         && type instanceof ChoiceType) {
      return _toClass(desc, im, (ChoiceType)type);
    } else if (desc != null
         && type instanceof EnumeratedType) {
      return _toClass(desc, im, (EnumeratedType)type);
    } else if (desc != null
         && type instanceof IntegerType) {
      return _toClass(desc, im, (IntegerType)type);
    } else if (desc != null
         && type instanceof OctetStringType) {
      return _toClass(desc, im, (OctetStringType)type);
    } else if (desc != null
         && type instanceof SequenceOfType) {
      return _toClass(desc, im, (SequenceOfType)type);
    } else if (desc != null
         && type instanceof SequenceType) {
      return _toClass(desc, im, (SequenceType)type);
    } else if (desc != null
         && type instanceof DefinedType) {
      return _toClass(desc, im, (DefinedType)type);
    } else if (desc != null
         && type != null) {
      return _toClass(desc, im, type);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(desc, im, type).toString());
    }
  }
  
  public CharSequence toField(final ComponentType type, final ImportManager im) {
    if (type instanceof AnyDefinedNamedType) {
      return _toField((AnyDefinedNamedType)type, im);
    } else if (type instanceof ComponentOfType) {
      return _toField((ComponentOfType)type, im);
    } else if (type instanceof NamedComponentType) {
      return _toField((NamedComponentType)type, im);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(type, im).toString());
    }
  }
  
  public CharSequence toField(final Type type, final ImportManager im, final String attributeName) {
    if (type instanceof IA5String) {
      return _toField((IA5String)type, im, attributeName);
    } else if (type instanceof ChoiceType) {
      return _toField((ChoiceType)type, im, attributeName);
    } else if (type instanceof IntegerType) {
      return _toField((IntegerType)type, im, attributeName);
    } else if (type instanceof OctetStringType) {
      return _toField((OctetStringType)type, im, attributeName);
    } else if (type instanceof SequenceOfType) {
      return _toField((SequenceOfType)type, im, attributeName);
    } else if (type instanceof DefinedType) {
      return _toField((DefinedType)type, im, attributeName);
    } else if (type != null) {
      return _toField(type, im, attributeName);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(type, im, attributeName).toString());
    }
  }
  
  public CharSequence toConstraintAnnotation(final GenConstraint<Long> constraint, final ImportManager im) {
    if (constraint instanceof GenSizeConstraint) {
      return _toConstraintAnnotation((GenSizeConstraint<Long>)constraint, im);
    } else if (constraint instanceof GenValueRangeConstraint) {
      return _toConstraintAnnotation((GenValueRangeConstraint<Long>)constraint, im);
    } else if (constraint == null) {
      return _toConstraintAnnotation((Void)null, im);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(constraint, im).toString());
    }
  }
  
  public CharSequence toEnumFieldOfChoiceType(final Type type, final String enumFieldName, final ImportManager im) {
    if (type instanceof TaggedType) {
      return _toEnumFieldOfChoiceType((TaggedType)type, enumFieldName, im);
    } else if (type != null) {
      return _toEnumFieldOfChoiceType(type, enumFieldName, im);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(type, enumFieldName, im).toString());
    }
  }
  
  public String getReference(final Type type, final ImportManager im) {
    if (type instanceof OctetStringType) {
      return _getReference((OctetStringType)type, im);
    } else if (type instanceof DefinedType) {
      return _getReference((DefinedType)type, im);
    } else if (type != null) {
      return _getReference(type, im);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(type, im).toString());
    }
  }
}
